-
Notifications
You must be signed in to change notification settings - Fork 975
Conversation
Right now I'm working on the recovery flow. The thing I need help with is figuring out a good approach for printing / saving the keys! @ayumi for recovering keys do I just have an aboutAction that ipc's to ledger.js and then a method in ledger.js that calls client.recover? I'm still trying to get my head around the ledger.js -> ledger-client -> ledger workflow @bradleyrichter on the recover modal we have "Recover" and "Done" but I think it might cause some confusion where entering your keys and clicking "Done" seems like it should do a recover. Maybe we can remove "Done" or change it to "Cancel"? Also, we're gonna need a better approach for organizing all these modals. I read this thread (reactjs/react-modal#75) which pointed to an interesting approach: https://github.com/react-rally/www/blob/gh-pages/2015/app/screens/Schedule/index.js#L152-L180 |
df5b17b
to
acec001
Compare
@jkup good catch. This should fix the UX issue: |
acec001
to
3d9d3c2
Compare
@jkup yes, the appAction IPC -> ledger thing sounds legit |
5dac2e3
to
85e9db8
Compare
fc02edc
to
a637fc7
Compare
This one is getting close. Could I get some eyes on the communication from @bbondy or @bridiver. Right now preferences.js triggers and aboutAction to appStore to ledger.js (which is all working but maybe not the best approach. Then (the last part I'm struggling with is getting the data back to preferences.js from ledger.js. I tried (as you can see in this branch) just emitting an ipc event but that doesn't seem to be working. I can see that the recover task is working correctly, I just need to get that info back to the UI. |
@jkup you communicate back to preferences by updating the state |
@@ -583,6 +586,27 @@ const handleAppAction = (action) => { | |||
case AppConstants.APP_SET_DICTIONARY: | |||
appState = appState.setIn(['dictionary', 'locale'], action.locale) | |||
break | |||
case AppConstants.APP_BACKUP_KEYS: | |||
const paymentId = appState.get('ledgerInfo').get('paymentId') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you want to encapsulate this in a ledger.js method
}) | ||
break | ||
case AppConstants.APP_RECOVER_WALLET: | ||
ipcMain.emit(messages.LEDGER_RECOVER_WALLET, action.firstRecoveryKey, action.secondRecoveryKey) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above. ledger.js
runs in the same process as appStore.js
so emitting an ipc event doesn't really make sense. Just call a method on ledger.js - see https://github.com/brave/browser-laptop/compare/tabs-api?expand=1#diff-23ca389e2bcb77191b5a9c10900eb3a3R717 for an example. The methods should always take the state and the action (reducer) as parameters and return the state (may or may not be modified). The flow should almost always be the same: call an action -> reducer functions update state in appStore -> ui updates to reflect the new state
@@ -88,6 +88,38 @@ const aboutActions = { | |||
}, | |||
|
|||
/** | |||
* Generates a file with the users backup keys | |||
*/ | |||
generateKeyFile: function (backupAction) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would probably be helpful to give these actions/constants names that include ledger
. Eventually we'll probably break them out into ledger actions
@@ -722,7 +722,17 @@ class TabsTab extends ImmutableComponent { | |||
class PaymentsTab extends ImmutableComponent { | |||
constructor () { | |||
super() | |||
this.state = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please put the state in AboutPreferences
and pass it to PaymentTab
as props.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you help me understand why? Will I also need to create and pass down actions for updating those keys as well? Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. @bbondy can explain why
case AppConstants.APP_BACKUP_KEYS: | ||
const paymentId = appState.get('ledgerInfo').get('paymentId') | ||
const passphrase = appState.get('ledgerInfo').get('passphrase') | ||
const message = 'Your ledger keys are ' + paymentId + ' and ' + passphrase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be localized
const message = 'Your ledger keys are ' + paymentId + ' and ' + passphrase | ||
const filePath = app.getPath('userData') + '/backup_keys.html' | ||
|
||
fs.writeFile(filePath, message) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think this should be writeFileSync
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
writeFileSync will block the entire browser process. Is there a particular reason for sync over a callback?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bridiver sorry, i meant either writeFileSync or put the rest of the block in the callback
@@ -478,8 +478,12 @@ WindowStore | |||
percentage: number, // i.e., 0, 1, ... 100 | |||
publisherURL: string, // publisher site, e.g., "https://wikipedia.org/" | |||
faviconURL: string // i.e., "data:image/...;base64,..." | |||
} ], | |||
options: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be useful to give this a more descriptive name, like synopsisOptions
, because this property gets merged into ledgerData in js/components/frame.js
@@ -583,6 +586,27 @@ const handleAppAction = (action) => { | |||
case AppConstants.APP_SET_DICTIONARY: | |||
appState = appState.setIn(['dictionary', 'locale'], action.locale) | |||
break | |||
case AppConstants.APP_BACKUP_KEYS: | |||
const paymentId = appState.get('ledgerInfo').get('paymentId') | |||
const passphrase = appState.get('ledgerInfo').get('passphrase') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use getIn
here and in the line above to avoid chaining gets
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fyi - getIn
is helpful because you'll never get an undefined method on null when accessing nested props
please add a test or two for this in test/components/braveryPanelTest.js |
pushing a fix for unicode thing now |
address #4396 (comment) Auditors: @aekeus Test Plan: 1. go to ledger panel, save recovery keys 2. verify that opening the saved file in the browser does not show non-ascii characters
@@ -585,6 +587,21 @@ const handleAppAction = (action) => { | |||
case AppConstants.APP_SET_DICTIONARY: | |||
appState = appState.setIn(['dictionary', 'locale'], action.locale) | |||
break | |||
case AppConstants.APP_BACKUP_KEYS: | |||
ledger.backupKeys(appState, action) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be appState = ledger.backupKeys(appState, action)
to capture any state updates that this method might make. I know it doesn't directly make any now, but the pattern should always be the same to avoid confusion
ledger.backupKeys(appState, action) | ||
break | ||
case AppConstants.APP_RECOVER_WALLET: | ||
ledger.recoverKeys(appState, action) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
*/ | ||
|
||
var recoverKeys = (appState, action) => { | ||
client.recoverWallet(action.firstRecoveryKey, action.secondRecoveryKey, (err, body) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this callback may or may not happen asynchronously so the appActions should be called inside setImmediate
to prevent any potential race conditions with state updates. The issue was discussed in slack, but this is how it happens:
For simplicity, all actions increment the current count by 1, but the same problem exists even if the actions change different parts of the state
1. action1 is called with the current appState = {count: 0}
2. action1 calls a method with a callback
3. callback returns synchronously (does not perform any io or other operations that would make it async)
4. action2 is called inside callback with the current appState = {count: 0}
5. action2 returns appState = {count: 1}
6. appState is emitted
7. action1 returns appState = {count: 1}
8 app state is emitted
++ |
git rebase -i
to squash commits (if needed).Fixes #3350
Auditors @bbondy @bradleyrichter
Still remaining